<?php

namespace Application\Services;

use Phalcon\Exception;
use Thrift\Protocol\TBinaryProtocol;
use Thrift\Protocol\TMultiplexedProtocol;
use Thrift\Transport\TBufferedTransport;
use Thrift\Transport\TSocket;

/**
 * Class BaseService 服务类的继承基类
 * @description 子类必须实现设置服务方法命名规则为xxxService
 * @package Application\Services
 */
abstract class BaseService
{
    protected $service = null;
    protected $transport = null;
    private $serviceName = "";
    private static $registerServices = [];
    private $suffix = "Service";
    private $clientClessSubffix = "Client";
    private $serviceNamespace = "BlogServices";

    public function __construct($address, $port)
    {
        //多服务实例化模式
        $serviceName = $this->setServiceName();
        if (strpos($serviceName, $this->suffix) === false) {
            throw new Exception('服务' . $serviceName . '必须以' . $this->suffix . '结尾 ');
        }
        $this->serviceName = ucfirst(strtolower(str_replace($this->suffix, '', $serviceName))) . $this->suffix;
        BaseService::$registerServices = $this->registerServices();
        if (!in_array($this->serviceName, array_keys(BaseService::$registerServices))) {
            throw new Exception('服务必须在BaseService::registerServices内添加');
        } else {
            if (BaseService::$registerServices[$this->serviceName] != null) {
                $this->service = BaseService::$registerServices[$this->serviceName];
                return;
            }
        }
        $socket = new TSocket($address, $port);
        $socket->setRecvTimeout(1000);
        $socket->setSendTimeout(1000);
        $this->transport = new TBufferedTransport($socket);
        $protocol = new TMultiplexedProtocol(new TBinaryProtocol($this->transport), $this->serviceName);
        $serviceClassName = $this->serviceNamespace . "\\" . $this->serviceName . $this->clientClessSubffix;
        $this->service = new $serviceClassName($protocol);
        try {
            $this->transport->open();
            BaseService::$registerServices[$this->serviceName] = $this->service;
        } catch (Exception $e) {
            throw new Exception($e->getMessage());
        }
    }

    public function close()
    {
        if ($this->transport) {
            $this->transport->close();
        }
    }

    /**
     * @return array
     */
    private function registerServices()
    {
        return [
            'ArticleService' => null,
            'MenuService' => null,
            'CategoryService' => null,
            'ConfigService' => null,
            'LinkService' => null,
            'TagService' => null
        ];
    }

    abstract public function setServiceName();

    public function __destruct()
    {
        try {
            $this->close();
        } catch (Exception $e) {

        }
    }
}